# data cleaning
library(tidyverse)
# visualization
library(plotly)
library(scales)
library(glue)
library(hrbrthemes)
library(viridis)data_ab <- read.csv(file = "udacity_ab.csv", stringsAsFactors = F)
# head digunakan untuk menampilkan 6 data awal
head(data_ab)Dari hasil diatas bisa dilihat bahwa terdapat 5 kolom beberapa deskripsi dari kolom tersebut seperti berikut:
userid : unik id user yang mengidentifikasi setiap pengguna.timestamp : urutan karakter atau informasi yang dikodekan yang mengidentifikasi kapan peristiwa tertentu terjadigroup : apakah user masuk ke dalam grup control atau grup treatmentlanding_page : jenis landing page yang didapatkan oleh user, old_page (control) atau new_page (treatment)converted : apakah user convert terhadap produk (yes=1; no=0)str(data_ab)#> 'data.frame': 294478 obs. of 5 variables:
#> $ user_id : int 851104 804228 661590 853541 864975 936923 679687 719014 817355 839785 ...
#> $ timestamp : chr "2017-01-21 22:11:48.556739" "2017-01-12 08:01:45.159739" "2017-01-11 16:55:06.154213" "2017-01-08 18:28:03.143765" ...
#> $ group : chr "control" "control" "treatment" "treatment" ...
#> $ landing_page: chr "old_page" "old_page" "new_page" "new_page" ...
#> $ converted : int 0 0 0 0 1 0 1 0 1 1 ...
data_ab merupakan sebuah ‘data.frame’ atau tabel dengan 294,478 baris dan 5 kolom. Terdiri dari kolom user_id, timestamp, group, landing_page, converted.
Sebelum masuk lebih dalam mengenai A/B testing, kita melakukan eksplorasi pada data yang ada. Kita bisa menghitung banyaknya user yang masuk dalam kelompok control dan treatment.
# untuk menghitung frekuensi kemunculan data
table(data_ab$group)#>
#> control treatment
#> 147202 147276
Insight: Ternyata pada user game yang kita miliki, user yang termasuk pada grup treatment lebih banyak dibandingkan dengan user pada grup control.
data_ab_clean <- data_ab %>%
mutate(user_id = as.character(user_id),
landing_page = str_replace(landing_page, "_", " ") %>%
str_to_title() %>%
as.factor(),
date = as.Date(data_ab$timestamp),
group = as.factor(group),
converted = as.factor(converted))
summary(data_ab_clean)#> user_id timestamp group landing_page
#> Length:294478 Length:294478 control :147202 New Page:147239
#> Class :character Class :character treatment:147276 Old Page:147239
#> Mode :character Mode :character
#>
#>
#>
#> converted date
#> 0:259241 Min. :2017-01-02
#> 1: 35237 1st Qu.:2017-01-08
#> Median :2017-01-13
#> Mean :2017-01-13
#> 3rd Qu.:2017-01-19
#> Max. :2017-01-24
str(data_ab_clean)#> 'data.frame': 294478 obs. of 6 variables:
#> $ user_id : chr "851104" "804228" "661590" "853541" ...
#> $ timestamp : chr "2017-01-21 22:11:48.556739" "2017-01-12 08:01:45.159739" "2017-01-11 16:55:06.154213" "2017-01-08 18:28:03.143765" ...
#> $ group : Factor w/ 2 levels "control","treatment": 1 1 2 2 1 1 2 1 2 2 ...
#> $ landing_page: Factor w/ 2 levels "New Page","Old Page": 2 2 1 1 2 2 1 2 1 1 ...
#> $ converted : Factor w/ 2 levels "0","1": 1 1 1 1 2 1 2 1 2 2 ...
#> $ date : Date, format: "2017-01-21" "2017-01-12" ...
Kita akan coba melihat proporsi dari masing-masing grup yang ada.
prop.table(table(data_ab_clean$group))*100#>
#> control treatment
#> 49.98744 50.01256
Proporsi grup control dan grup treatment memiliki proporsi yang seimbang. Hal ini merupakan sampel yang cukup baik dalam pengujian A/B testing.
Selanjutnya hal lain yang perlu diperhatikan yaitu memeriksa apakah ada nilai missing untuk setiap variabel.
# cara 1
anyNA(data_ab_clean)#> [1] FALSE
# cara 2
colSums(is.na(data_ab_clean))#> user_id timestamp group landing_page converted date
#> 0 0 0 0 0 0
Tidak terdapat missing value pada data
Cek terlebih dahulu apakah terdapat duplikasi pada data yang ada.
duplicated(data_ab_clean) %>% sum()#> [1] 0
Tidak terdapat duplicate pada data
number_of_convert <- data_ab_clean %>%
group_by(converted) %>%
count()
number_of_convertTerdapat 35,237 user atau sekitar 12% dari total user yang convert terhadap produk yang ditawarkan.
convert_per_day <- data_ab_clean %>%
filter(converted == 1) %>%
group_by(date) %>%
count()
convert_per_dayplot_day <- convert_per_day %>%
ggplot(aes(x = date, y = n
)) +
geom_area(fill = "#69b3a2", alpha = 0.5) +
geom_line(color="#69b3a2") +
labs(title = "Number of Convert per Day in January 2017", x = "Day", y = "Number of Convert")+
theme_minimal()
# Turn it interactive with ggplotly
ggplotly(plot_day)Terlihat bahwa jumlah convert cenderung stabil setiap harinya di sepanjang bulan Januari 2027.
Sebuah landing page perlu memiliki conversion rate yang tinggi sebagai dasar untuk landing page yang baik. Metrik yang menunjukkan bahwa landing page berhasil dapat dianalisis bagaimana jumlah konversinya (converted). Converted adalah kondisi dimana user subscribe/purchase produk yang kita miliki.
Sekarang kita akan hitung persentase pemain yang tertarik dengan landing page dengan indikasi converted-nya.
prop.table(table("Converted" = data_ab_clean$converted))*100#> Converted
#> 0 1
#> 88.03408 11.96592
Ternyata sebesar 12% user convert ke produk yang kita miliki. Persentase tersebut masih rendah apabila dibandingkan dengan user yang memutuskan untuk tidak convert.
Apabila dianalisa lebih lanjut konversi untuk masing-masing peletakan landing page yang berbeda adalah sebagai berikut.
ratio_per_group <- data_ab_clean %>%
group_by(group, converted) %>%
summarize(count =n()) %>%
mutate(percentage = round(count/sum(count)*100,2)) %>%
arrange(converted) %>%
ungroup()
ratio_per_groupUntuk kedua peletakan landing page tersebut, jumlah konversi hampir sama yaitu sekitar 12%.
# perbedaan conversion pada treatment dan control
11.89 - 12.04#> [1] -0.15
Ternyata dengan menganalisa berdasarkan Conversion Rate, terdapat perbedaan sebesar -0.15% antara peletakkan landing page pada control dan treatment.
Hal pertama untuk melihat perbedaan antara dua grup, kita akan menganalisis distribusi untuk masing-masing grup dan melihat seberapa jauh perbedaannya untuk kedua grup tersebut.
Persentase user yang convert pada control sedikit lebih tinggi daripada untuk treatment. Skornya sangat kecil karena perbedaannya sekitar 0.15%. Untuk meningkatkan kepercayaan diri kita dengan perbedaan yang sangat kecil tersebut, kita dapat menggunakan metode bootstrap sampling untuk dapat kita jadikan sebuah gambaran bagaimana pengaruhnya angka ini pada masa mendatang.
Pertama, kita akan membagi data menjadi dua grup Pengguna di grup control dan di grup treatment akan dianalisa untuk masing-masing grup.
data_control <- data_ab_clean %>%
filter(group == "control")
data_treatment <- data_ab_clean %>%
filter(group == "treatment")Metode bootstrap sampling akan membuat sebuah data yang hampir mirip namun dengan mengizinkan adanya replacement. Untuk mendapatkan kepercayaan lebih, maka interasi dalam replikasi datanya akan dibuat hingga 10,000 sampel.
# sampling <- 10000
# new_data_control <- NULL
# new_data_treatment <- NULL
# set.seed(9999)
#
# for(i in 1:sampling)
# {
# n_control <- length(data_control$converted)
# bootmarks_control <- data_control[sample(1:n_control,replace=TRUE),]
# new_number_control <- sum(bootmarks_control$converted == 1)/n_control
#
# new_data_control <- c(new_data_control,new_number_control)
# }
#
# for(i in 1:sampling)
# {
# n_treatment <- length(data_treatment$converted)
# bootmarks_treatment <- data_treatment[sample(1:n_treatment,replace=TRUE),]
# new_number_treatment <- sum(bootmarks_treatment$converted == 1)/n_treatment
#
# new_data_treatment <- c(new_data_treatment,new_number_treatment)
# }Selanjutnya, mari kita lihat distribusi datanya.
data_conversion <- data.frame(
gate = c( rep("Control", length(new_data_control)), rep("Treatment", length(new_data_treatment)) ),
value = c(new_data_control, new_data_treatment)
)
data_conversion %>%
ggplot( aes(x=as.numeric(value), fill=gate)) +
geom_density( color="#e9ecef", alpha=0.7) +
scale_fill_manual(values=c("#69b3a2", "#404080")) +
xlab("Conversion Rate")+
ggtitle("Conversion Rate Distribution")+
theme_ipsum() +
labs(fill="")Dari plot di atas, kita dapat melihat perbedaan antara kedua kelompok. Plot menunjukkan bahwa tingkat konversi untuk control lebih tinggi daripada di treatment. Namun, perbedaannya terlihat sangat kecil.
Kita juga bisa melihat distribusi dari masing-masing kelompok dengan melihat perbedaan persentasenya. Untuk melakukan ini, kita dapat membuat kolom baru yang berisi informasi selisih dari rata-rata nilai conversion rate pada control dengan treatment.
data_difference <- as.data.frame(cbind(new_data_control, new_data_treatment)) %>%
mutate(diff = round(abs(new_data_control - new_data_treatment)*100,2))
head(data_difference)data_difference %>%
ggplot( aes(x=diff)) +
geom_density( color="#e9ecef", fill = "#c90076", alpha=0.7) +
scale_fill_manual(values="#8fce00") +
xlab("Conversion Rate Diff")+
ggtitle("Gap Conversion Rate Distribution")+
theme_ipsum() +
labs(fill="")Dari plot di atas, selisih antara grup control dan grup treatment terletak antara 0 - 0.6%. Distribusi perbedaan conversion rate paling banyak mengumpul di antara 0,1% sampai 0,2%. Ini menunjukkan perbedaan yang tidak cukup jelas antara peletakan landing page di control (old page) dan treatment (new page).
Sebagai kesimpulan, mari kita coba cek probabilitas conversion rate yang tidak sama dengan 0%. Hal ini akan dilakukan untuk mengetahui efek dari peletakan landing page pada level yang berbeda.
data_difference %>%
count(diff == 0)Ada tiga hal yang harus disertakan dalam A/B testing diantaranya yaitu signifikansi perbedaan antara grup control dan grup treatment, confidence interval, dan statistics power experiment. Tiga hal di sini sangat menentukan seberapa baik A/B testing telah dijalankan dan bagaimana kita memandang ide baru di masa depan.
Kita telah menganalisis perbedaan antara grup control dan grup treatment sebelumnya dengan melihat distribusi masing-masing grup. Untuk lebih meyakinkan seberapa yakin perbedaan tersebut, kita akan menggunakan uji statistik untuk melihat apakah grup treatment lebih baik dari grup control atau tidak. Untuk melakukan ini, kita akan menggunakan uji chi-square dengan menggunakan alpha 5%. Nilai p-value yang diinginkan untuk conversion rate harus lebih rendah dari 5%.
Hipotesis untuk uji signifikansi dijelaskan sebagai berikut:
$$
H_0: Tidak ada perbedaan signifikan antara conversion rate pada grup control dan grup treatment\
H_1: Ada perbedaan signifikan antara conversion rate pada grup control dan grup treatment
$$
Uji Chi-Square untuk conversion rate 1 hari dapat diperoleh p-value sebagai berikut:
chi_square <- table(data_ab_clean$group, data_ab_clean$converted)
chisq.test(chi_square)#>
#> Pearson's Chi-squared test with Yates' continuity correction
#>
#> data: chi_square
#> X-squared = 1.516, df = 1, p-value = 0.2182
Karena p-value > alpha dimana 0.2182 > 0.05, maka kesimpulan dari hipotesis kita yaitu tak tolak H0, artinya tidak ada perbedaan yang signifikan antara conversion rate pada control dan treatment.
Hasil uji signifikansi ternyata menyatakan bahwa hipotesis tidak signifikan. Kita tetap dapat melanjutkan untuk melihat CI dan statistical power-nya. Namun, hal ini dapat dijadikan pertimbangan bahwa kemungkinan nilai CI yang diperoleh pun akan menunjukkan bahwa treatment yang dilakukan tidak berhasil.
Kita telah mengetahui perbedaan antara grup control dan grup treatment hanya dengan mencari selisih dari conversion rate-nya. Misalnya, pada conversion rate pada grup control sebesar 12.04% sedangkan pada grup treatment sebesar 11.89%. Sedangkan pada conversion rate 7 hari pada grup control sebesar 18.20% sedangkan pada grup treatment sebesar 19.02%. Berdasarkan nilai tersebut, kita ingin mengetahui berapa rentang retention rate yang akan diperoleh dalam 1 hari ataupun 7 hari.
ratio_per_groupmencari nilai d yang merupakan hasil dari conversion pada treatment dikurang conversion pada control
d <- 0.1189 - 0.1204
d#> [1] -0.0015
Berdasarkan nilai d atau selisih conversion rate landing page lama dengan landing page baru ternyata nilainya negatif, artinya penerapan landing page baru kurang menarik minat user. Namun, selisihnya terbilang sangatlah kecil. Maka kita akan coba melihat Confidence Interval-nya
Mencari tahu sampel dari masing-masing grup untuk retensi 1 hari.
table(data_ab_clean$group, data_ab_clean$converted)#>
#> 0 1
#> control 129479 17723
#> treatment 129762 17514
Menghitung \(\hat{p}_{pool}\).
p_pool <- (17723+17514)/nrow(data_ab_clean)
se_pool <- sqrt(p_pool * (1 - p_pool) * (1/(129479 + 17723) + 1/ (129762 + 17514)))Menghitung batas atas dan batas bawah.
upper_conversion <- d + 1.96*se_pool
lower_conversion <- d - 1.96*se_pool
lower_conversion*100 ; upper_conversion*100#> [1] -0.3844542
#> [1] 0.08445425
Kita mendapat confidence interval antara -0.38% hingga 0.08%. Rentang ini menunjukkan 95% dari menempatkan landing page pada landing page baru akan menambah tingkat konversi antara -0.38% hingga 0.08%.
Saat nilai CI pada conversion rate berada di rentang lower negatif (-) hingga upper positif (+) atau melewati angka 0%, artinya ada kondisi dimana nilai conversion rate bisa mencapai 0%. Ketika conversion rate bernilai 0% artinya treatment yang diberikan kurang berhasil dalam artian fitur baru yang akan dibuat kurang menarik perhatian konsumen sehingga akan lebih baik jika fitur tersebut tidak dijalankan. Bisa juga dikatakan bahwa tidak ada perbedaan antara control dengan treatment yang diberikan.
Dalam pengujian statistik terdapat type I error atau yang lebih sering dikenal dengan \(\alpha\) dimana fungsinya yaitu mencari tahu probabilitas suatu pengujian menunjukkan perbedaan, tetapi pada kenyataannya hasilnya sebenarnya tidak terdapat perbedaan. Sedangkan, type II error atau lebih sering dinotasikan sebagai \(\beta\) adalah suatu probabilitas dalam mengidentifikasi apabila terdapat varian A dan B yang sebenarnya berbeda, tetapi dalam pengujian gagal mendeteksinya. Simpelnya type II error biasanya disebut sebagai statistical power di mana fungsinya adalah untuk mengetahui probabilitas suatu pengujian dalam mendeteksi “true” efek ketika efek tersebut memang benar-benar terjadi.
Formula yang biasanya digunakan untuk mencari power analisis yaitu:
di mana:
Misalkan dalam conversion rate landing page ini, kita akan fokus pada peningkatan perubahan 1% pada landing page yang berbeda dan confidence level yang akan digunakan sebesar 95%.
Untuk melakukan power analysis, kita perlu mencari tahu terlebih dahulu conversion rate pada grup control.
prop.table(table(data_ab_clean$group, data_ab_clean$converted), margin = 1)#>
#> 0 1
#> control 0.8796008 0.1203992
#> treatment 0.8810804 0.1189196
Nilai conversion rate pada grup kontrol sebesar 0.1204. Berdasarkan nilai tersebut, kita coba hitung nilai sigma.
sigma <- sqrt(0.1204*(1-0.1204))
sigma#> [1] 0.3254287
Selanjutnya, kita cari tahu jumlah sampel untuk masing-masing grup.
table(data_ab_clean$group, data_ab_clean$converted)#>
#> 0 1
#> control 129479 17723
#> treatment 129762 17514
Menggunakan jumlah sampel masing-masing grup, kita coba hitung nilai \(Z_\beta\).
z <- (sqrt(min(129479 + 17723, 129762 + 17514)) * 0.01)/(2 * sigma) - 1.96
# untuk mencari probability nilai power
pnorm(z)#> [1] 0.9999584
Insight: pada kasus ini, kita yakin 99.99% bahwa tidak terjadi kenaikan maupun penurunan (CI akan mendekati 0%) apabila experiment dengan landing page baru benar-benar dilakukan.